using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 区域和特效管理器
    /// </summary>
    public class LevelPlayAreaEffectCtrl : LevelPlaySubBaseCtrl
    {
        /// <summary>
        /// 当前的区域
        /// </summary>
        public EntityParamArea currentAreaParam { private set; get; }
        public LevelPlayBaseEntity currentAreaEntity { get; private set; }

        /// <summary>
        /// 特效的Root
        /// </summary>
        public Transform effectRoot { private set; get; }

        /// <summary>
        /// 离开当前区域
        /// </summary>
        private void ExitCurrentArea()
        {
            if (currentAreaParam == null)
            {
                return;
            }
            this.regionCtrl.cameraCtrl.RecoverCameraAfterExitArea();
            ClearAreaEffect();

            currentAreaParam = null;
            currentAreaEntity = null;
        }

        /// <summary>
        /// 进入一个新的区域
        /// </summary>
        /// <param name="newArea"></param>
        private void EnterNewArea(EntityParamArea newArea, LevelPlayBaseEntity areaEntity)
        {
            this.currentAreaParam = newArea;
            this.currentAreaEntity = areaEntity;

            if (currentAreaParam.cameraCid > 0)
            {
                this.regionCtrl.cameraCtrl.ChangeCharacterCamera(currentAreaParam.cameraCid);
            }

            if (currentAreaParam.sceneEffectCid > 0)
            {
                ShowSceneEffectById(currentAreaParam.sceneEffectCid, SceneEffectType.Area).Forget();
            }
            var dynEntity = areaEntity.GetDynLevelEntity();
            if (dynEntity?.areaEffectCids == null)
            {
                return;
            }
            foreach (var effectCid in dynEntity.areaEffectCids)
            {
                if (effectCid != currentAreaParam.sceneEffectCid)
                {
                    ShowSceneEffectById(effectCid, SceneEffectType.Area).Forget();
                }
            }

            //if (currentArea.sceneTimeCid > 0)
            //{
            //    this.levelPlayCtrl.sceneCtrl.ChangeSceneRenderTimeById(currentArea.sceneTimeCid).Forget();
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paramValueList"></param>
        public void AreaListParamChanged(IReadOnlyList<BaseEntityDynamicParam> paramValueList, IReadOnlyList<LevelPlayBaseEntity> entityList)
        {
            if (paramValueList.Count == 0)
            {
                ExitCurrentArea();
                MsgDispatcher.Broadcast(MsgEventType.Level_TriggerAreaChanged);
                return;
            }
            if (currentAreaParam == null)
            {
                EnterNewArea(paramValueList[0] as EntityParamArea, entityList[0]);
                MsgDispatcher.Broadcast(MsgEventType.Level_TriggerAreaChanged);
                return;
            }
            for (var i = 0; i < paramValueList.Count; i++)
            {
                if (currentAreaParam == paramValueList[i])
                {
                    // 还处在当前区域，无需更改区域
                    return;
                }
            }
            ExitCurrentArea();
            EnterNewArea(paramValueList[0] as EntityParamArea, entityList[0]);
            MsgDispatcher.Broadcast(MsgEventType.Level_TriggerAreaChanged);
        }

        /// <summary>
        /// 通知改变区域特效组
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="sceneEffectId"></param>
        /// <param name="isAdd"></param>
        public void OnNotifyChangeAreaEffectGroup(int areaEntityId, int sceneEffectId, bool isAdd)
        {
            bool isGlobal = areaEntityId <= 0;
            if (areaEntityId != 0)
            {
                if (regionCtrl.entityCtrl.entitys.TryGetValue(areaEntityId, out var entity))
                {
                    entity.GetDynLevelEntity().ChangeAreaEffect(sceneEffectId, isAdd);
                }
            }
            if (isAdd)
            {
                if (isGlobal)
                {
                    ShowSceneEffectById(sceneEffectId, SceneEffectType.Global).Forget();
                    return;
                }
                if (currentAreaEntity != null && currentAreaEntity.id == areaEntityId) //正好处在修改特效的区域内，则直接修改特效表现
                {
                    ShowSceneEffectById(sceneEffectId, SceneEffectType.Area).Forget();
                }
            }
            else
            {
                if (isGlobal)
                {
                    RemoveSceneEffectById(sceneEffectId, SceneEffectType.Global);
                    return;
                }
                if (currentAreaEntity != null && currentAreaEntity.id == areaEntityId) //正好处在修改特效的区域内，则直接修改特效表现
                {
                    RemoveSceneEffectById(sceneEffectId, SceneEffectType.Area);
                }
            }
        }
        #region Effect

        public HashSet<int> areaEffectMapping = new();

        public HashSet<int> globalEffectMapping = new();

        /// <summary>
        /// 添加一个特效
        /// </summary>
        /// <param name="sceneEffectId"></param>
        /// <param name="isArea"></param>
        /// <returns></returns>
        public async UniTask<LevelSceneEffectView> ShowSceneEffectById(int sceneEffectId, SceneEffectType sceneEffectType)
        {
            switch (sceneEffectType)
            {
                case SceneEffectType.Area:
                    if (areaEffectMapping.Contains(sceneEffectId))
                    {
#if UNITY_EDITOR
                        LogGame.Log("[LevelPlayAreaEffectCtrl|ShowSceneEffectById]  effectUnit already exist,id:" + sceneEffectId.ToString());
#endif
                        return null;
                    }
                    break;
                case SceneEffectType.Global:
                    if (globalEffectMapping.Contains(sceneEffectId))
                    {
#if UNITY_EDITOR
                        LogGame.Log("[LevelPlayAreaEffectCtrl|ShowSceneEffectById]  effectUnit already existk,id:" + sceneEffectId.ToString());
#endif
                        return null;
                    }
                    break;
            }

            var effectUnit = await regionCtrl.effectCtrl.ShowSceneEffect(sceneEffectId, effectRoot) as LevelSceneEffectView;
            if (effectUnit == null)
            {
                return null;
            }
            switch (sceneEffectType)
            {
                case SceneEffectType.Area:
                    areaEffectMapping.Add(sceneEffectId);
                    break;
                case SceneEffectType.Global:
                    globalEffectMapping.Add(sceneEffectId);
                    break;
            }
            await effectUnit.Load();

            return effectUnit;
        }

        public bool RemoveSceneEffectById(int sceneEffectId, SceneEffectType sceneEffectType)
        {
            switch (sceneEffectType)
            {
                case SceneEffectType.Area:
                    areaEffectMapping.Remove(sceneEffectId);
                    break;
                case SceneEffectType.Global:
                    areaEffectMapping.Remove(sceneEffectId);
                    break;
                default:
                    return false;
            }
            regionCtrl.effectCtrl.HideSceneEffect(sceneEffectId);
            return true;
        }

        /// <summary>
        /// 清除所有区域型特效
        /// </summary>
        public void ClearAreaEffect()
        {
            foreach (var cid in areaEffectMapping)
            {
                regionCtrl.effectCtrl.HideSceneEffect(cid);
            }
            areaEffectMapping.Clear();
        }

        public void ClearGlobalEffect()
        {
            foreach (var cid in globalEffectMapping)
            {
                regionCtrl.effectCtrl.HideSceneEffect(cid);
            }
            globalEffectMapping.Clear();
        }

        #endregion

        #region 生命周期

        protected override void OnModuleGameplayInit()
        {

        }

        protected override void OnSceneLoaded()
        {
            MsgDispatcher.AddListener<int, int, bool>(MsgEventType.Level_NotifyChangeAreaEffectGroup, OnNotifyChangeAreaEffectGroup);

            effectRoot = new GameObject("EffectRoot").transform;
            effectRoot.position = Vector3.zero;

            foreach (var effectCid in regionCtrl.levelRegion.effectCids)
            {
                ShowSceneEffectById(effectCid, SceneEffectType.Global).Forget();
            }
        }

        protected override void OnDispose()
        {
            MsgDispatcher.RemoveListener<int, int, bool>(MsgEventType.Level_NotifyChangeAreaEffectGroup, OnNotifyChangeAreaEffectGroup);
        }

        #endregion

    }
}